package com.kylin.common.core.config.support;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONPObject;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
import com.kylin.common.core.annotation.JSONSerialized;
import com.kylin.common.core.beans.ResultBean;
import org.apache.commons.lang3.SerializationUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 重写fastjson配置解析
 *
 * @author wuhao
 * @version 1.0 - 2019-08-19
 */
public class KylinFastJsonHttpMessageConverter extends FastJsonHttpMessageConverter {

    private FastJsonConfig fastJsonConfig = new FastJsonConfig();

    /**
     * @return the fastJsonConfig.
     * @since 1.2.11
     */
    @Override
    public FastJsonConfig getFastJsonConfig() {
        return fastJsonConfig;
    }

    /**
     * @param fastJsonConfig the fastJsonConfig to set.
     * @since 1.2.11
     */
    @Override
    public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
        this.fastJsonConfig = fastJsonConfig;
    }

    @Override
    protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

//        try (ByteArrayOutputStream outnew = new ByteArrayOutputStream();) {
//            HttpHeaders headers = outputMessage.getHeaders();
//
//            //获取全局配置的filter
//            Filter[] writerFilters = fastJsonConfig.getWriterFilters();
//            List<Filter> allFilters = new ArrayList<>(Arrays.asList(writerFilters));
//
//            boolean isJsonp = false;
//
//            //不知道为什么会有这行代码， 但是为了保持和原来的行为一致，还是保留下来
////            Object value = customStrangeCodeForJackson(object);
//
////            if (value instanceof FastJsonContainer) {
////                FastJsonContainer fastJsonContainer = (FastJsonContainer) value;
////                PropertyPreFilters filters = fastJsonContainer.getFilters();
////                allFilters.addAll(filters.getFilters());
////                value = fastJsonContainer.getValue();
////            }
//
//            //revise 2017-10-23 ,
//            // 保持原有的MappingFastJsonValue对象的contentType不做修改 保持旧版兼容。
//            // 但是新的JSONPObject将返回标准的contentType：application/javascript ，不对是否有function进行判断
//            if (value instanceof JSONPObject) {
//                isJsonp = true;
//            }
//
//            //获取序列化的注解信息
//            if(object instanceof ResultBean){
//                JSONSerialized[] jsonSerializeds = ((ResultBean) object).getJsonSerialized();
//                if(jsonSerializeds != null) {
//                    for(JSONSerialized jsonSerialized : jsonSerializeds) {
//                        String[] includes = jsonSerialized.includes();
//                        SimplePropertyPreFilter simplePropertyPreFilter = new SimplePropertyPreFilter(jsonSerialized.clazz(), includes);
//                        allFilters.add(simplePropertyPreFilter);
//                    }
//                }
//            }
//
//            // 注解忽略NULL 过滤
//
//
//            int len = JSON.writeJSONString(outnew,
//                    fastJsonConfig.getCharset(),
//                    value,
//                    fastJsonConfig.getSerializeConfig(),
//                    //fastJsonConfig.getSerializeFilters(), //
//                    allFilters.toArray(new SerializeFilter[allFilters.size()]),
//                    fastJsonConfig.getDateFormat(),
//                    JSON.DEFAULT_GENERATE_FEATURE,
//                    fastJsonConfig.getSerializerFeatures());
//
//            if (isJsonp) {
//                headers.setContentType(APPLICATION_JAVASCRIPT);
//            }
//
//            if (fastJsonConfig.isWriteContentLength()) {
//                headers.setContentLength(len);
//            }
//
//            outnew.writeTo(outputMessage.getBody());
//
//        } catch (JSONException ex) {
//            throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
//        }

        HttpHeaders headers = outputMessage.getHeaders();

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            //*************************** 源码改造 ***************************//
            //获取全局配置的filter
            Filter[] writerFilters = fastJsonConfig.getWriterFilters();
            List<Filter> allFilters = new ArrayList<>(Arrays.asList(writerFilters));

            //获取序列化的注解信息
            if(object instanceof ResultBean){
                JSONSerialized[] jsonSerializeds = ((ResultBean) object).getJsonSerialized();
                if(jsonSerializeds != null) {
                    for(JSONSerialized jsonSerialized : jsonSerializeds) {
                        String[] includes = jsonSerialized.includes();
                        SimplePropertyPreFilter simplePropertyPreFilter = new SimplePropertyPreFilter(jsonSerialized.clazz(), includes);
                        allFilters.add(simplePropertyPreFilter);
                    }
                }
            }

            //*************************** 源码改造 end ***************************//
            try {
                int contentLength;
                byte[] strBytes;
                if (object instanceof String && JSON.isValidObject((String)object)) {
                    strBytes = ((String)object).getBytes(this.fastJsonConfig.getCharset());
                    contentLength = strBytes.length;
                    outputMessage.getBody().write(strBytes, 0, strBytes.length);
                } else if (object instanceof byte[] && JSON.isValid((byte[])object)) {
                    strBytes = (byte[])object;
                    contentLength = strBytes.length;
                    outputMessage.getBody().write(strBytes, 0, strBytes.length);
                } else {
                    if (object instanceof JSONPObject) {
                        headers.setContentType(APPLICATION_JAVASCRIPT);
                    }

                    contentLength = JSON.writeTo(baos, object, this.fastJsonConfig.getDateFormat(), allFilters.toArray(new Filter[allFilters.size()]), this.fastJsonConfig.getWriterFeatures());
                }

                if (headers.getContentLength() < 0L && this.fastJsonConfig.isWriteContentLength()) {
                    headers.setContentLength((long)contentLength);
                }

                baos.writeTo(outputMessage.getBody());
            } catch (Throwable var8) {
                try {
                    baos.close();
                } catch (Throwable var7) {
                    var8.addSuppressed(var7);
                }

                throw var8;
            }

            baos.close();
        } catch (JSONException var9) {
            throw new HttpMessageNotWritableException("Could not write JSON: " + var9.getMessage(), var9);
        } catch (IOException var10) {
            throw new HttpMessageNotWritableException("I/O error while writing output message", var10);
        }
    }


    private Object customStrangeCodeForJackson(Object obj) {
        if (obj != null) {
            String className = obj.getClass().getName();
            if ("com.fasterxml.jackson.databind.node.ObjectNode".equals(className)) {
                return obj.toString();
            }
        }
        return obj;
    }
}
